package org.geohunter.activity.osmmap;

import org.andnav.osm.ResourceProxy;
import org.andnav.osm.views.OpenStreetMapView;
import org.andnav.osm.views.OpenStreetMapView.OpenStreetMapViewProjection;
import org.andnav.osm.views.overlay.OpenStreetMapViewOverlay;

import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;

import java.util.List;

public class OsmPinOverlay extends OpenStreetMapViewOverlay {
    
    // ===========================================================
    // Constants
    // ===========================================================

    // ===========================================================
    // Fields
    // ===========================================================

    protected OnItemTapListener<OsmPinItem> mOnItemTapListener;
    protected final List<OsmPinItem> mItemList;

    // ===========================================================
    // Constructors
    // ===========================================================

    public OsmPinOverlay(List<OsmPinItem> list,
            OnItemTapListener<OsmPinItem> aOnItemTapListener, 
            ResourceProxy resourceProxy) {
        super(resourceProxy);
        this.mItemList = list;
        this.mOnItemTapListener = aOnItemTapListener;
    }

    // ===========================================================
    // Getter & Setter
    // ===========================================================

    // ===========================================================
    // Methods from SuperClass/Interfaces
    // ===========================================================

    @Override
    protected void onDrawFinished(Canvas c, OpenStreetMapView osmv) {
        return;
    }

    @Override
    public void onDraw(final Canvas c, final OpenStreetMapView mapView) {
        final OpenStreetMapViewProjection pj = mapView.getProjection();

        final Point curScreenCoords = new Point();

        Matrix matrix = c.getMatrix();
        /* Draw in backward cycle, so the items with the least index are on the front. */
        for(int i = this.mItemList.size() - 1; i >= 0; i--){
            OsmPinItem item = this.mItemList.get(i);
            pj.toMapPixels(item.mGeoPoint, curScreenCoords);

            onDrawItem(c, i, curScreenCoords);
        }
        c.setMatrix(matrix);  //Restore old matrix
    }

    protected void onDrawItem(final Canvas c, final int index, 
            final Point curScreenCoords) {
        Drawable pin = mItemList.get(index).mPin;
        
        final int width = pin.getIntrinsicWidth();
        final int height = pin.getIntrinsicHeight();
        final int left = curScreenCoords.x - width / 2;
        final int right = left + width - 1;
        final int top = curScreenCoords.y - height + 1;
        final int bottom = curScreenCoords.y;
        //Log.d("geohunter", "OsmPinOverlay.onDrawItem " + index + " left="+left+" top="+top);
        pin.setBounds(left, top, right, bottom);
        pin.draw(c);
        
        //TODO: Does this work?
        /*
        Matrix matrix = new Matrix();
        matrix.setTranslate(curScreenCoords.x, curScreenCoords.y);
        c.setMatrix(matrix);
        pin.draw(c);
        */
    }

    @Override
    public boolean onSingleTapUp(final MotionEvent event, 
            final OpenStreetMapView mapView) {
        final OpenStreetMapViewProjection pj = mapView.getProjection();
        final int eventX = (int) event.getX();
        final int eventY = (int) event.getY();

        /* These objects are created to avoid construct new ones every cycle. */
        final Rect curMarkerBounds = new Rect();
        final Point curScreenCoords = new Point();
        final Point curScreenCoords2 = new Point();

        for(int i = 0; i < this.mItemList.size(); i++){
            final OsmPinItem item = this.mItemList.get(i);
            final int markerWidth = item.mPin.getIntrinsicWidth();
            final int markerHeight = item.mPin.getIntrinsicHeight();

            pj.toMapPixels(item.mGeoPoint, curScreenCoords);

            final int left = (curScreenCoords.x - markerWidth / 2);
            final int right = left + markerWidth;
            final int top = curScreenCoords.y - markerHeight;
            final int bottom = curScreenCoords.y;
            curMarkerBounds.set(left, top, right, bottom);

            pj.fromMapPixels(eventX, eventY, curScreenCoords2);
            if (curMarkerBounds.contains(curScreenCoords2.x, curScreenCoords2.y)) {
                if (onTap(i)) {
                    return true;
                }
            }
        }
        return super.onSingleTapUp(event, mapView);
    }

    // ===========================================================
    // Methods
    // ===========================================================

    protected boolean onTap(int pIndex) {
        if(this.mOnItemTapListener != null)
            return this.mOnItemTapListener.onItemTap(pIndex, this.mItemList.get(pIndex));
        else
            return false;
    }

    // ===========================================================
    // Inner and Anonymous Classes
    // ===========================================================
    public static interface OnItemTapListener<T>{
        public boolean onItemTap(final int aIndex, final T aItem);
    }

}
